package com.sy.simpleegg.platform.kkb.network.manager

import android.annotation.SuppressLint
import android.net.wifi.WifiManager
import android.text.TextUtils
import android.util.ArrayMap
import cn.ych.network.errorhandler.ExceptionHandle
import cn.ych.network.observer.BaseResultObserver
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.aliyun.alink.linkkit.api.ILinkKitConnectListener
import com.aliyun.alink.linksdk.tools.AError
import com.blankj.utilcode.constant.TimeConstants
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ThreadUtils.SimpleTask
import com.blankj.utilcode.util.TimeUtils
import com.sy.simpleegg.platform.kkb.bean.device.ConnectTestEntity
import com.sy.simpleegg.platform.kkb.bean.device.DeviceStatusBean
import com.sy.simpleegg.platform.kkb.bean.device.DeviceUpdateEntity
import com.sy.simpleegg.platform.kkb.bean.device.HeartbeatEntity
import com.sy.simpleegg.platform.kkb.bean.device.RegisterEntity
import com.sy.simpleegg.platform.kkb.bean.device.RemoteDeviceConfigEntity
import com.sy.simpleegg.platform.kkb.bean.device.SubRegisterEntity
import com.sy.simpleegg.platform.kkb.bean.device.UpdatesDTO
import com.sy.simpleegg.platform.kkb.loader.DeviceConnectLoader
import com.sy.simpleegg.platform.kkb.network.base.BaseResult
import com.sy.simpleegg.platform.kkb.network.base.IDeviceManager
import com.ych.ytdevicesdk.config.App
import com.ych.ytdevicesdk.config.Constants
import com.ych.ytdevicesdk.entity.AliDataEntity
import com.ych.ytdevicesdk.entity.AppInfoEntity
import com.ych.ytdevicesdk.entity.MqCoinEntity
import com.ych.ytdevicesdk.entity.MqDeviceSetRequestData
import com.ych.ytdevicesdk.utils.AliMessageEntity
import com.ych.ytdevicesdk.utils.AliMessageQueueUtils
import com.ych.ytdevicesdk.utils.FileUtils
import com.ych.ytdevicesdk.utils.LogUtilsX
import com.ych.ytdevicesdk.utils.SignatureUtils
import io.reactivex.Observer
import java.text.SimpleDateFormat
import java.util.Date
import java.util.TreeMap
import java.util.concurrent.TimeUnit
import kotlin.concurrent.Volatile

/**
 * @author sy
 * @date 2024/10/11 17:10
 * @desc
 */
class DeviceManager : IDeviceManager {
    private val deviceConnectLoader = DeviceConnectLoader()
    private var aliMessageQueueUtils: AliMessageQueueUtils? = null
    private var isOpenLog = false
    private var isDebug = false
    private var useTestUrl = false
    private var agreement = 1
    private var agreementVer = "0"
    private val cmdBufferStack: ArrayMap<String?, Int?> = ArrayMap<String?, Int?>()
    private val mQCoinBufferStack: ArrayMap<String?, MqCoinEntity?> = ArrayMap<String?, MqCoinEntity?>()
    private var mQResponseTimes = 0
    private var productFlag = "00010001"

    @Volatile
    private var instance: IDeviceManager? = null
    private var initListener: IDeviceManager.InitListener? = null
    private var eventListener: IDeviceManager.IMqMessageListener? = null
    private var data: RemoteDeviceConfigEntity? = null
    private var getDeviceConfigCount = 0
    private var mAliMqRetryCount = 0

    fun getInstance(): IDeviceManager? {
        if (instance == null) {
            val var0: Class<*> = DeviceManager::class.java
            synchronized(DeviceManager::class.java) {
                if (instance == null) {
                    instance = DeviceManager()
                }
            }
        }
        return instance
    }

    companion object {
        @kotlin.jvm.Volatile
        @SuppressLint("StaticFieldLeak")
        var instance: IDeviceManager? = null

        fun singleInstance(): IDeviceManager {
            if (instance == null) {
                synchronized(DeviceManager::class) {
                    if (instance == null) {
                        instance = DeviceManager()
                    }
                }
            }
            return instance!!
        }
    }

    override fun getDeviceNumber(): String? {
        return Constants.DEVICE_NUMBER
    }

    override fun initSdk(
        appKey: String,
        mainBoardNum: String,
        deviceType: String,
        agreement: Int,
        agreementVer: String,
        vararg appInfoEntity: AppInfoEntity?,
    ): IDeviceManager? {
//        Constants.MAIN_BOARD_NUM = mainBoardNum
//        setAgreementInfo(agreement, agreementVer, "00010001")
//        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
//        map["OSVer"] = DeviceUtils.getSDKVersionCode()
//        map["MainBoardNum"] = mainBoardNum
//        map["Memery"] = Runtime.getRuntime().maxMemory() / 1024L
//        map["Disk"] = SDCardUtils.getInternalTotalSize() / 1048576L
//        map["OSName"] = "Android"
//        map["OSVerName"] = DeviceUtils.getSDKVersionName()
//        map["RegCode"] = appKey
//        map["DeviceType"] = deviceType
//        val appInfos: Array<out AppInfoEntity?> = appInfoEntity
//        val size = appInfoEntity.size
//        for (i in 0 until size) {
//            val infoEntity = appInfos[i]
//            infoEntity?.hardVer = 9
//        }
//        map["AppInfo"] = JSONObject.toJSON(appInfoEntity)
//        getUniversalMac(map)
//        deviceConnectLoader.registerProduct(
//            map,
//            object : BaseResultObserver<BaseResult<RegisterEntity?>>() {
//                override fun onSuccess(result: BaseResult<RegisterEntity?>) {
//                    val data = result.getData()
//                    LogUtils.d(*arrayOf<Any>("RegisterEntity response : " + JSON.toJSONString(result)))
//                    if (data != null) {
//                        Constants.SIGN_KEY = data.AppKey
//                        Constants.DEVICE_NUMBER = data.DeviceName
//                        initAliMq(data)
//                        heartbeat(1L, 11)
//                        checkUpdate(*appInfoEntity)
//                    }
//                }
//
//                override fun onFailure(e: Throwable) {
//                    if (initListener != null) {
//                        if (e is ExceptionHandle.ResponeThrowable) {
//                            val throwablex = e as ExceptionHandle.ResponeThrowable
//                            initListener!!.registerFailed(throwablex.code, throwablex.message)
//                        } else if (e is ExceptionHandle.ServerException) {
//                            val throwable = e as ExceptionHandle.ResponeThrowable
//                            initListener!!.registerFailed(throwable.code, throwable.message)
//                        } else {
//                            initListener!!.registerFailed(-9999L, e.message)
//                        }
//                    }
//                }
//            })
        return instance
    }

    override fun setAgreementInfo(agreement: Int, agreementVer: String, productFlag: String) {
        this.agreement = agreement
        this.agreementVer = agreementVer
        this.productFlag = productFlag
    }

    private fun checkUpdate(vararg appInfoEntity: AppInfoEntity?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["Apps"] = JSONObject.toJSON(appInfoEntity)
        getUniversalMac(map)
        deviceConnectLoader.checkUpdate(
            map,
            object : BaseResultObserver<BaseResult<DeviceUpdateEntity?>>() {
                override fun onSuccess(baseResult: BaseResult<DeviceUpdateEntity?>) {
                    val data = baseResult.data as DeviceUpdateEntity
                    if (data != null && data.Updates != null) {
                        if (data.Updates.isEmpty()) {
                            this@DeviceManager.getDeviceConfig()
                        } else {
                            if (initListener != null) {
                                val updateUrls: ArrayList<Any?> = ArrayList<Any?>(3)
                                val var4: Iterator<*> =
                                    (baseResult.data as DeviceUpdateEntity).Updates!!.iterator()
                                while (var4.hasNext()) {
                                    val update = var4.next() as UpdatesDTO
                                    updateUrls.add(update.DownUrlval)
                                }
                                val updateUrlArrays = arrayOfNulls<String>(updateUrls.size)
                                initListener!!.needUpdate(
                                    *updateUrls.toArray<String?>(
                                        updateUrlArrays
                                    ) as Array<String?>
                                )
                            }
                            this@DeviceManager.getDeviceConfig()
                        }
                    } else {
                        this.onFailure(Throwable("无法获取更新信息"))
                    }
                }

                override fun onFailure(e: Throwable) {
                    universalFailure("UPDATE", e)
                }
            })
    }

    override fun getDeviceConfig() {
        this.getDeviceConfig(Constants.hardwareDeviceId)
    }

    override fun getDeviceConfig(hardwareId: String?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        if (hardwareId != null) {
            map["MachineMacID"] = hardwareId
        }
        getUniversalMac(map)
        deviceConnectLoader.getDeviceConfig(
            map,
            object : BaseResultObserver<BaseResult<RemoteDeviceConfigEntity?>?>() {
                override fun onSuccess(entityBaseResult: BaseResult<RemoteDeviceConfigEntity?>?) {
                    if (entityBaseResult == null) {
                        this.onFailure(Throwable("未能获取到配置信息"))
                    } else {
                        data = entityBaseResult.data
                        if (data == null) {
                            this.onFailure(Throwable("未能获取到配置信息"))
                        } else {
                            getDeviceConfigCount++
                            if (data!!.StepIndex == 0) {
                                ThreadUtils.runOnUiThreadDelayed({
                                    if (getDeviceConfigCount >= 3) {
                                        LogUtilsX.e("DeviceConfig\n重试3次后失败")
                                        initListener!!.bindStatus(
                                            false,
                                            Constants.DEVICE_NUMBER
                                        )
                                    } else {
                                        this@DeviceManager.getDeviceConfig(hardwareId)
                                    }
                                }, 2000L)
                            } else {
                                getDeviceConfigCount = 0
                                Constants.BASE_BUSINESS_URL = data!!.LocalServer
                                if (Constants.BASE_BUSINESS_URL == null || Constants.BASE_BUSINESS_URL.isEmpty()) {
                                    Constants.BASE_BUSINESS_URL = data!!.BizServer
                                }
                                if (Constants.BASE_BUSINESS_URL == null || Constants.BASE_BUSINESS_URL.isEmpty()) {
                                    LogUtilsX.e("DeviceConfig\nBASE_URL获取失败" + data.toString())
                                }
                                if (initListener != null) {
                                    if (Constants.BASE_BUSINESS_URL == null || Constants.BASE_BUSINESS_URL.isEmpty()) {
                                        LogUtilsX.e(
                                            """
                                        DeviceConfig
                                        getDeviceConfigCount=${getDeviceConfigCount}\nBASE_URL获取失败${data.toString()}
                                        """.trimIndent()
                                        )
                                    }
                                    initListener!!.bindStatus(
                                        data!!.StepIndex != 0,
                                        Constants.DEVICE_NUMBER
                                    )
                                }
                            }
                        }
                    }
                }

                override fun onFailure(e: Throwable) {
                    universalFailure("BIND", e)
                }
            })
    }

    override fun getBaseBusinessUrl(): String? {
        return Constants.BASE_BUSINESS_URL
    }

    override fun getRemoteDeviceConfigData(): RemoteDeviceConfigEntity? {
        return data
    }

    fun mqResponse(mTransId: String) {
        this.mqResponse(mTransId, 0, "")
    }

    fun mqResponse(mTransID: String, result: Int, msg: String?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["TimeStamp"] = TimeUtils.getNowMills() / 1000L
        map["Result"] = result
        map["Message"] = msg
        map["TransID"] = mTransID
        getUniversalMac(map)
        deviceConnectLoader.messageQueueResult(
            map,
            object : BaseResultObserver<BaseResult<Any?>?>() {
                override fun onSuccess(stringBaseResult: BaseResult<Any?>?) {
                    LogUtils.i(*arrayOf<Any>("回复 MQ ： mTransID  -> " + mTransID))
                }

                override fun onFailure(throwable: Throwable) {}
            })
    }

    private fun initAliMq(data: RegisterEntity) {
        aliMessageQueueUtils =
            AliMessageQueueUtils.getInstance().isDebug(isDebug).initLog(isOpenLog)
                .registerPushConnect().initMessageQuery(
                    data.ProductKey,
                    data.DeviceName,
                    data.DeviceKey,
                    object : ILinkKitConnectListener {
                        override fun onError(error: AError) {
                            LogUtils.e(*arrayOf<Any>("LinkKit onError : " + JSON.toJSON(error)))
                            FileUtils.writeFile("阿里MQ连接失败：" + JSON.toJSON(error))
                            mAliMqRetryCount++
                            if (initListener != null) {
                                initListener!!.registerFailed(
                                    error.code.toLong(),
                                    error.msg + ", 重试次数: " + mAliMqRetryCount
                                )
                            }
                            AliMessageQueueUtils.getInstance().disConnect()
                            ThreadUtils.runOnUiThreadDelayed({ initAliMq(data) }, 10000L)
                        }

                        override fun onInitDone(datax: Any) {
                            mAliMqRetryCount = 0
                            FileUtils.writeFile("阿里MQ连接成功 初始化")
                            aliMessageQueueUtils!!.mqSubscription()
                        }
                    }).setDeviceConnectListener { isConnect: Boolean ->
                    if (isConnect) {
                        FileUtils.writeFile("阿里MQ连接成功")
                    } else {
                        FileUtils.writeFile("阿里MQ断开连接")
                        if (initListener != null) {
                            initListener!!.onError(
                                "CONNECT",
                                -9999L,
                                "MQTT 连接断开"
                            )
                        }
                    }
                }.setEventListener { aliMessageEntity: AliMessageEntity? ->
                    if (aliMessageEntity != null) {
                        if (eventListener != null && !Constants.isCrashToCoin) {
                            LogUtils.i(
                                *arrayOf<Any>(
                                    "收到 MQ command ->" + aliMessageEntity.command + " \nTransID ->" + aliMessageEntity.transID
                                )
                            )
                            val dataJson: String
                            when (aliMessageEntity.command) {
                                "Bind" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    getDeviceConfigCount = 0
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.deviceBinding()
                                }

                                "Unbind" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.deviceUnBinding()
                                }

                                "Reboot" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.deviceReBoot()
                                }

                                "ExtractCoin" -> {
                                    if (Constants.deviceIsMaintenance) {
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            351,
                                            "兑币机停用"
                                        )
                                        return@setEventListener
                                    }
                                    extractCoin(aliMessageEntity)
                                }

                                "ChangeCashPackage" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.changeCashPackage()
                                }

                                "SetSetting" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    dataJson = JSON.toJSONString(aliMessageEntity.data)
                                    ThreadUtils.executeByIo<Int>(object : SimpleTask<Int>() {
                                        @Throws(Throwable::class)
                                        override fun doInBackground(): Int? {
                                            return eventListener!!.setDeviceSetting(
                                                dataJson
                                            )
                                        }

                                        override fun onSuccess(responseCode: Int) {
                                            if (responseCode == null) {
                                                this@DeviceManager.mqResponse(aliMessageEntity.transID)
                                            } else {
                                                this@DeviceManager.mqResponse(
                                                    aliMessageEntity.transID,
                                                    responseCode,
                                                    ""
                                                )
                                            }
                                            cmdBufferStack[aliMessageEntity.transID] =
                                                responseCode
                                        }
                                    }, 10)
                                }

                                "GetSetting" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    dataJson = JSON.toJSONString(aliMessageEntity.data)
                                    ThreadUtils.executeByIo<Map<Int?, Any?>>(
                                        object :
                                            SimpleTask<Map<Int?, Any?>?>() {
                                            @Throws(Throwable::class)
                                            override fun doInBackground(): Map<Int?, Any?>? {
                                                return eventListener!!.getDeviceSetting(
                                                    dataJson
                                                )
                                            }

                                            override fun onSuccess(responseCode: Map<Int?, Any?>?) {
                                                if (responseCode == null) {
                                                    mqResponse(
                                                        aliMessageEntity.transID,
                                                        1,
                                                        "未获取到响应信息"
                                                    )
                                                } else {
                                                    mqResponse(
                                                        aliMessageEntity.transID,
                                                        0,
                                                        ""
                                                    )
                                                }
                                                cmdBufferStack.put(
                                                    aliMessageEntity.transID,
                                                    0
                                                )
                                            }
                                        },
                                        10
                                    )
                                }

                                "SyncDev" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        return@setEventListener
                                    }
                                    dataJson = JSON.toJSONString(aliMessageEntity.data)
                                    LogUtils.e(
                                        *arrayOf<Any>(
                                            "===停用指令： " + dataJson
                                        )
                                    )
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    var status = 1
                                    if (!TextUtils.isEmpty(dataJson)) {
                                        val json = JSON.parseObject(
                                            dataJson,
                                            DeviceStatusBean::class.java
                                        ) as DeviceStatusBean
                                        if (json != null) {
                                            status = json.State
                                        }
                                    }
                                    eventListener!!.deviceStatues(status)
                                    this.mqResponse(aliMessageEntity.transID)
                                }

                                else -> this.mqResponse(aliMessageEntity.transID)
                            }
                        } else {
                            this.mqResponse(
                                aliMessageEntity.transID,
                                301,
                                "设备繁忙"
                            )
                            Constants.isCrashToCoin = false
                        }
                    }
                }
    }

    override fun pushDeviceSetting(hardwareId: String?, dataList: List<MqDeviceSetRequestData?>?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["Atts"] = dataList
        map["MacID"] = this.getMacId()
        deviceConnectLoader.pushDeviceSet(map, object : BaseResultObserver<BaseResult<Any?>?>() {
            override fun onSuccess(objectBaseResult: BaseResult<Any?>?) {}
            override fun onFailure(e: Throwable) {}
        })
    }

    override fun disMqConnect() {
        if (aliMessageQueueUtils != null) {
            aliMessageQueueUtils!!.disSubscription()
            aliMessageQueueUtils!!.disConnect()
        }
    }

    override fun initSdk(
        appKey: String?,
        mainBoardNum: String?,
        deviceType: String?,
        agreement: Int,
        agreementVer: String?,
        appInfoEntity: AppInfoEntity?,
        initListener: IDeviceManager.InitListener?,
    ): IDeviceManager? {
//        return this.initSdk(
//            appKey!!, mainBoardNum!!, deviceType!!, agreement, agreementVer!!,
//            appInfoEntity!!
//        )!!.setInitListener(initListener)
        return instance
    }

    override fun setInitListener(initListener: IDeviceManager.InitListener?): IDeviceManager? {
        this.initListener = initListener
        return instance
    }

    override fun debugger(isOpen: Boolean, useTestUrl: Boolean): IDeviceManager? {
        isDebug = isOpen
        this.useTestUrl = useTestUrl
        deviceConnectLoader.setIsDebug(useTestUrl)
        return instance
    }

    override fun logger(isOpen: Boolean): IDeviceManager? {
        isOpenLog = isOpen
        return instance
    }

    override fun connectTest(iConnectTestResponse: IDeviceManager.IConnectTestResponse?): IDeviceManager? {
        deviceConnectLoader.connectTest(object :
            BaseResultObserver<BaseResult<ConnectTestEntity?>>() {
            override fun onSuccess(result: BaseResult<ConnectTestEntity?>) {
                LogUtils.d(*arrayOf<Any>("ConnectTestEntity : $result"))
                iConnectTestResponse?.callBack(true, null as String?)
                val data = result.data as ConnectTestEntity
                val timestamp = data.Timestamp
                val timeStampStr =
                    TimeUtils.millis2String(timestamp * 1000L + Constants.STANDARD_TIME_SPAN)
                Constants.NOW_TIME_SPAN =
                    TimeUtils.getTimeSpanByNow(timestamp * 1000L + Constants.STANDARD_TIME_SPAN, TimeConstants.MSEC)
                LogUtils.d(
                    *arrayOf<Any>(
                        String.format(
                            "timeStampStr : %s -> timeStamp : %s",
                            timeStampStr,
                            timestamp * 1000L + Constants.STANDARD_TIME_SPAN
                        )
                    )
                )
            }

            override fun onFailure(e: Throwable) {
                iConnectTestResponse?.callBack(false, e.message)
                universalFailure("CONNECT", e)
            }
        })
        return instance
    }

    fun heartbeat(wait: Long, deviceType: Int) {
        ThreadUtils.executeBySingleWithDelay<Boolean>(object : SimpleTask<Boolean?>() {
            @Throws(Throwable::class)
            override fun doInBackground(): Boolean? {
                val wifiManager =
                    App.getAppContext().applicationContext.getSystemService("wifi") as WifiManager
                val connectionInfo = wifiManager.connectionInfo
                val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
                if (connectionInfo != null) {
                    map["SSID"] = connectionInfo.ssid
                    map["Signal"] = connectionInfo.rssi
                    map["Delay"] = connectionInfo.linkSpeed
                } else {
                    map["SSID"] = ""
                    map["Signal"] = 100
                    map["Delay"] = 30
                }
                map["Agreement"] = agreement
                map["AgreeVer"] = agreementVer
                map["DeviceType"] = deviceType
                map["ProductNumber"] = "0x" + productFlag
                getUniversalMac(map)
                deviceConnectLoader.deviceHeartbeat(
                    map,
                    object : BaseResultObserver<BaseResult<HeartbeatEntity?>?>() {
                        override fun onSuccess(stringBaseResult: BaseResult<HeartbeatEntity?>?) {
                            heartbeat(300L, deviceType)
                        }

                        override fun onFailure(e: Throwable) {
                            universalFailure("heartbeat", e)
                            heartbeat(300L, deviceType)
                        }
                    })
                return null
            }

            override fun onSuccess(result: Boolean?) {}
        }, wait, TimeUnit.SECONDS, 10)
    }

    override fun subDeviceRegister(
        machineID: String?,
        productCode: String?,
        hardVer: Int,
        softVer: Int,
        appName: String?,
        appTitle: String?,
        observer: Observer<BaseResult<SubRegisterEntity?>?>?,
    ) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["MachineID"] = machineID
        map["ProductCode"] = "0x$productCode"
        map["HardVer"] = hardVer
        map["SoftVer"] = softVer
        map["AppName"] = appName
        map["AppTitle"] = appTitle
        map["Union"] = 1
        getUniversalMac(map)
        observer?.let {
            deviceConnectLoader.subDeviceRegister(map, it)
        }
    }

    override fun deviceErrorSubmit(errorType: Int, errorMsg: String?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["ErrorCode"] = errorType
        map["FaultDeviceType"] = 1
        map["Urgent"] = 2
        getUniversalMac(map)
        deviceConnectLoader.pushDeviceError(map, object : BaseResultObserver<BaseResult<Any?>?>() {
            override fun onSuccess(stringBaseResult: BaseResult<Any?>?) {}
            override fun onFailure(e: Throwable) {
                universalFailure("DEVICE_ERROR", e)
            }
        })
    }

    private fun getUniversalMac(map: MutableMap<String?, Any?>) {
        map["MacID"] = this.getMacId()
        map["TimeSpan"] = TimeUtils.getNowMills()
    }

    override fun getMacId(): String? {
        return getMacId(Constants.MAIN_BOARD_NUM)
    }

    fun getMacId(macId: String): String? {
        val signatureTemp = SignatureUtils.getSignature(macId, "3A5B6BF5FAB891783A5B6CF4FAF79275")
        return macId + signatureTemp.substring(0, 4)
    }

    override fun setEventListener(eventListener: IDeviceManager.IMqMessageListener?): IDeviceManager? {
        this.eventListener = eventListener
        return instance
    }

    private fun universalFailure(errorType: String, e: Throwable) {
        if (initListener != null) {
            if (e is ExceptionHandle.ResponeThrowable) {
                val throwable = e as ExceptionHandle.ResponeThrowable
                initListener!!.onError(errorType, throwable.code, throwable.message)
            } else if (e is ExceptionHandle.ServerException) {
                val throwable = e as ExceptionHandle.ResponeThrowable
                initListener!!.onError(errorType, throwable.code, throwable.message)
            } else {
                initListener!!.onError(errorType, -9999L, e.message)
            }
        }
    }

    override fun getSdkVersion(): String {
        return "1.0.0.9"
    }

    private fun extractCoin(aliMessageEntity: AliMessageEntity) {
        LogUtils.e(*arrayOf<Any>("----收到出币MQ"))
        val transTime = Constants.STANDARD_TIME_SPAN + aliMessageEntity.validityDate * 1000L
        LogUtils.d(*arrayOf<Any>("EXTRACT_COIN : " + TimeUtils.millis2String(transTime)))
        LogUtils.d(*arrayOf<Any>("EXTRACT_COIN : " + TimeUtils.millis2String(transTime - Constants.NOW_TIME_SPAN)))
        val timeSpanByNow = TimeUtils.getTimeSpanByNow(transTime - Constants.NOW_TIME_SPAN, TimeConstants.SEC)
        LogUtils.d(*arrayOf<Any>(String.format("EXTRACT_COIN : timeSpanByNow %s s", timeSpanByNow)))
        if (timeSpanByNow < -5L) {
            LogUtils.e(*arrayOf<Any>("----出币事件过期"))
            LogUtils.i(*arrayOf<Any>("EXTRACT_COIN : 过期事件"))
            if (eventListener != null) {
                eventListener!!.pushLog(
                    "MQ发出到设备 时间间隔 ：（S） " + timeSpanByNow + " \n出币事件过期: " + aliMessageEntity.toString()
                )
            }
        } else {
            val dataJson = JSON.toJSONString(aliMessageEntity.data)
            if (!mQCoinBufferStack.containsKey(aliMessageEntity.transID)) {
                mQCoinBufferStack[aliMessageEntity.transID] =
                    MqCoinEntity(getOrderId(dataJson), 1)
                LogUtils.e(
                    *arrayOf<Any>(
                        "----出币MQ添加到缓存中" + getOrderId(
                            dataJson
                        )
                    )
                )
                ThreadUtils.executeByIo<Int>(object : SimpleTask<Int>() {
                    @Throws(Throwable::class)
                    override fun doInBackground(): Int {
                        LogUtils.e(*arrayOf<Any>("----调用马达出币方法"))
                        return eventListener!!.extractCoin(dataJson)
                    }

                    override fun onSuccess(responseCode: Int) {
                        LogUtils.e(*arrayOf<Any>("----接收马达返回状态 = " + responseCode))
                        val entity = mQCoinBufferStack[aliMessageEntity.transID]
                        if (entity != null) {
                            entity.orderStatus = 3
                            entity.deviceStatus = responseCode
                            mQCoinBufferStack[aliMessageEntity.transID] = entity
                        }
                        mqExtractCoinResponse(aliMessageEntity.transID, responseCode, "")
                    }
                }, 10)
            } else {
                LogUtils.e(*arrayOf<Any>("----出币事件存在缓存中"))
                LogUtils.e(*arrayOf<Any>("指令已接受,正在处理中 ： " + aliMessageEntity.command))
                val mqCoinEntity = mQCoinBufferStack[aliMessageEntity.transID]
                if (mqCoinEntity != null && TextUtils.equals(
                        mqCoinEntity.orderId,
                        getOrderId(dataJson)
                    )
                ) {
                    LogUtils.e(*arrayOf<Any>("----缓存中有该订单"))
                    if (mqCoinEntity.orderStatus == 2 || mqCoinEntity.orderStatus == 5) {
                        LogUtils.e(*arrayOf<Any>("----该订单状态为未回复或者回复失败"))
                        mqCoinEntity.orderStatus = 3
                        mQCoinBufferStack[aliMessageEntity.transID] = mqCoinEntity
                        mqExtractCoinResponse(
                            aliMessageEntity.transID,
                            mqCoinEntity.deviceStatus,
                            ""
                        )
                    }
                }
            }
        }
    }

    fun mqExtractCoinResponse(mTransID: String, result: Int, msg: String) {
        FileUtils.writeFile("回复MQ：mTransID = $mTransID result = $result msg = $msg")
        if (result == 303) {
            LogUtils.e(*arrayOf<Any>("----回复MQ result = " + result))
            LogUtilsX.e(
                "303不回复出币MQ",
                "时间：" + getCurrentDate("yyyy-MM-dd HH:mm:ss") + "mTransID = " + mTransID + " result = " + result + " msg = " + msg
            )
        } else {
            LogUtils.e(*arrayOf<Any>("----回复MQ"))
            val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
            map["TimeStamp"] = TimeUtils.getNowMills() / 1000L
            map["Result"] = result
            map["Message"] = msg
            map["TransID"] = mTransID
            getUniversalMac(map)
            deviceConnectLoader.messageQueueResult(
                map,
                object : BaseResultObserver<BaseResult<Any?>?>() {
                    override fun onSuccess(stringBaseResult: BaseResult<Any?>?) {
                        LogUtils.e(*arrayOf<Any>("----MQ回复成功" + mTransID))
                        if (mQCoinBufferStack.containsKey(mTransID)) {
                            val entity = mQCoinBufferStack[mTransID]
                            entity!!.orderStatus = 4
                            mQCoinBufferStack[mTransID] = entity
                            eventListener!!.updateOrder(
                                entity.orderId,
                                mTransID,
                                entity.deviceStatus,
                                "MQ回复成功"
                            )
                        }
                        mQResponseTimes = 0
                    }

                    override fun onFailure(throwable: Throwable) {
                        LogUtils.e(*arrayOf<Any>("----MQ回复失败 失败次数 = " + mQResponseTimes))
                        if (eventListener != null) {
                            eventListener!!.pushLog(
                                "----MQ回复失败 失败次数 = " + mQResponseTimes + "   失败事务ID = " + mTransID + " \n " + throwable.message
                            )
                        }
                        if (mQResponseTimes < 3) {
                            mQResponseTimes++
                            mqExtractCoinResponse(mTransID, result, msg)
                        } else {
                            if (mQCoinBufferStack.containsKey(mTransID)) {
                                val entity = mQCoinBufferStack[mTransID]
                                entity!!.orderStatus = 5
                                mQCoinBufferStack[mTransID] = entity
                                eventListener!!.updateOrder(
                                    entity.orderId,
                                    mTransID,
                                    entity.deviceStatus,
                                    "MQ回复失败"
                                )
                            }
                            mQResponseTimes = 0
                        }
                    }
                })
        }
    }

    private fun getOrderId(dataJson: String): String {
        var orderId = ""
        if (!TextUtils.isEmpty(dataJson)) {
            val data = JSON.parseObject(
                dataJson,
                AliDataEntity::class.java
            ) as AliDataEntity
            if (data != null) {
                orderId = data.orderID
            }
        }
        return orderId
    }

    private fun getCurrentDate(format: String): String {
        var format: String? = format
        if (TextUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss"
        }
        val simpleDateFormat = SimpleDateFormat(format)
        return simpleDateFormat.format(Date())
    }
}